package com.agent.vpsserver.common.utils.common;


import com.google.common.collect.Lists;
import com.agent.vpsserver.common.utils.date.DateUtils;

import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.UUID;

import static com.agent.vpsserver.common.utils.date.DateUtils.ALL_PATTERN;

/**
 * @作 者: 侯建军
 * @日 期: 2018/11/19 13:18:42
 * @描 述: ID生成器
 */
public class IdUtils {

    /**
     * 自定义进制(0,1没有加入,容易与o,l混淆)
     */
    private static final char[] SEC_ARRAY = new char[]{'T', 'N', '6', 'B', 'G', 'H', 'm', 'v', 'Q', 'W', 'E', '8', 'A', 'h', 'c', 'S',
            '2', 'D', 'Z', 'X', '9', 'C', '7', 'P', 'U', 'F', 'R', '4', 'V', 'Y', 'k', '5', 'K', '3', 'M',
            'J', 'a', 'g', 'w', 'f', 'u'};

//    private static final char[] SEC_ARRAY = new char[]{'l', 'T', 'N', '6', 'B', 'G', 'H', 'm', 'v', 'Q', 'W', 'E', '8', 'A', 'h', 'c', 'S',
//            '2', 'D', 'Z', 'X', '9', 'C', '7', 'P', 'U', 'F', 'l', 'R', '4', 'V', 'Y', 'k', '5', 'I', 'K', '3', 'M',
//            'J', 'a', 'g', 'o', 'w', 'f', 'u', 'i'};
    /**
     * (不能与自定义进制有重复)
     */
    private static final char LIMIT = 'H';

    /**
     * 进制长度
     */
    private static final int SEC_ARRAY_LENGTH = SEC_ARRAY.length;

    /**
     * 邀请码长度,旧版本为6位数,新版7位数起步,防止uk冲突
     */
    private static final int INVITE_CODE_LENGTH = 7;

    /**
     * 私有化构造函数
     */
    private IdUtils() {

    }

    /**
     * 订单编号生成器
     *
     * @param middleVal 入参
     * @return String
     * @author ludezheng
     * @date 2022/6/14 12:10
     */
    public static String orderNo(String middleVal) {
        return dateNo(null, middleVal, 4, "-", 4);
    }

    /**
     * 日期格式编号生成器
     *
     * @param dateFormat   入参
     * @param middleVal    入参
     * @param middleLength 入参
     * @param middleSymbol 入参
     * @param suffixLength 入参
     * @return String
     * @author ludezheng
     * @date 2022/6/14 12:10
     */
    public static String dateNo(String dateFormat, String middleVal, Integer middleLength, String middleSymbol, Integer suffixLength) {
        if (StringUtils.isBlank(dateFormat)) {
            dateFormat = ALL_PATTERN;
        }
        List<String> list = Lists.newArrayList();
        String date2Str = DateUtils.date2Str(new Date(), dateFormat);
        list.add(date2Str);

        String middle = "";
        if (StringUtils.isNotBlank(middleVal)) {
            middle = dataToCode(Long.parseLong(middleVal), null == middleLength ? 4 : middleLength);
            list.add(middle);
        }
        String suffix = "";
        if (null != suffixLength) {
            suffix = genRandomNumber(suffixLength);
            list.add(suffix);
        }
        if (StringUtils.isNotBlank(middleSymbol)) {
            return String.join(middleSymbol, list);
        }
        return String.join("", list);

    }

    /**
     * 生成随机字符串(0-9)
     *
     * @param length length
     * @return String
     */
    public static String genRandomNumber(int length) {
        final String source = "1908253674";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(source.charAt(random.nextInt(source.length() - 1)));
        }
        return sb.toString();
    }

    /**
     * 生成随机字符串(0-9,A-Z)
     *
     * @param length length
     * @return String
     */
    public static String genRandomString(int length) {
        final String source = "bre1hi2fj3pyq4vws5askl6g7ot8ucdz90mn";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(source.charAt(random.nextInt(source.length() - 1)));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 生成随机字符串(0-9,a-z,A-Z,特殊符号)
     *
     * @param length length
     * @return String
     */
    public static String genRandomStr(int length) {
        final String source = "AbrBe1ChEDiF2fG=jH3IpJyQq@K4PLvMwO#Ns5aRsklS6g&T7oUt8Vu!WcdXz90YmZn";
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(source.charAt(random.nextInt(source.length() - 1)));
        }
        return sb.toString();
    }

    /**
     * 获取uuid
     *
     * @return
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 获取邀请码
     *
     * @param id
     * @return
     */
    public static String inviteCode(Long id) {
        return dataToCode(id, INVITE_CODE_LENGTH);
    }

    /**
     * 根据ID生成length位随机码
     *
     * @param id ID
     * @return 随机码
     */
    public static String dataToCode(long id, int length) {
        char[] buf = new char[32];
        int charPos = 32;

        while ((id / SEC_ARRAY_LENGTH) > 0) {
            int ind = (int) (id % SEC_ARRAY_LENGTH);
            buf[--charPos] = SEC_ARRAY[ind];
            id /= SEC_ARRAY_LENGTH;
        }
        buf[--charPos] = SEC_ARRAY[(int) (id % SEC_ARRAY_LENGTH)];
        String str = new String(buf, charPos, (32 - charPos));
        // 不够长度的自动随机补全
        if (str.length() < length) {
            StringBuilder sb = new StringBuilder();
            sb.append(LIMIT);
            Random rnd = new Random();
            for (int i = 1; i < length - str.length(); i++) {
                sb.append(SEC_ARRAY[rnd.nextInt(SEC_ARRAY_LENGTH)]);
            }
            str += sb.toString();
        }
        return str;
    }

    /**
     * 根据code解密元数据
     *
     * @param code
     * @return
     */
    public static long codeToData(String code) {
        char[] chs = code.toCharArray();
        long res = 0L;
        for (int i = 0; i < chs.length; i++) {
            int ind = 0;
            for (int j = 0; j < SEC_ARRAY_LENGTH; j++) {
                if (chs[i] == SEC_ARRAY[j]) {
                    ind = j;
                    break;
                }
            }
            if (chs[i] == LIMIT) {
                break;
            }
            if (i > 0) {
                res = res * SEC_ARRAY_LENGTH + ind;
            } else {
                res = ind;
            }
        }
        return res;
    }

//    public static void main(String[] args) {
//        String s = IdUtils.genRandomStr(16);
//        System.out.println(s);
//    }
}